(module tests-mp8 mzscheme
  
  (provide tests-for-run tests-for-check tests-for-parse)
  ;;;;;;;;;;;;;;;; tests ;;;;;;;;;;;;;;;;
  
  ;; the numbers are skewed from the numbers in the chapter.  We'll have
  ;; to fix this at some point.

  (printf "Loading test file for chapter 6~%")

  (define the-test-suite
 
    '(
      ;; Problem 1 - Raw Value 
      (modules-5*k+3-raw "
        module int1
         interface [abstract-type t
                    zero : t
                    succ : (t -> t)
                    pred : (t -> t)
                    is-zero : (t -> bool)]  
         implementation [type t = int
                        zero = 3
                        succ = proc(x : ?) -(x,-5)
                        pred = proc(x : ?) -(x,5)
                        is-zero = proc (x : ?) zero?(-(x,3))]

         import int1
         let zero = from int1 take zero
         in let succ = from int1 take succ
         in (succ (succ zero))"
        (from int1 take t) 13)
      
      ;; Problem 1 to-int
      (modules-5*k+3-to-int "
        module int2
         interface [abstract-type t
                    zero : t
                    succ : (t -> t)
                    pred : (t -> t)
                    is-zero : (t -> bool)]  
         implementation [type t = int
                         zero = 3
                         succ = proc(x : ?) -(x,3)
                         pred = proc(x : ?) -(x,-3)
                         is-zero = proc (x : ?) zero?(-(x,3))
                         ]
         import int2
         let z = from int2 take zero
         in let s = from int2 take succ
         in let p = from int2 take pred
         in let z? = from int2 take is-zero
         in letrec int to-int (x : from int2 take t) =
                       if (z? x) then 0
                          else -((to-int (p x)), -1)
         in (to-int (s (s z)))"
                  int 2)
      
      (modules-booleans-test-false "
         module mybool 
          interface [abstract-type t
                     true : t
                     false : t
                     and : (t -> (t -> t))
                     not : (t -> t)
                     to-bool : (t -> bool)]
          implementation [type t = int
                          true = 26
                          false = 27
                          and = proc (x : t) 
                                 proc (y : t)
                                  if zero?(-(x,26)) then y else false
                          not = proc (x : t) 
                                 if zero?(-(x,26)) then false else true
                          to-bool = proc (x : t)  
                                     if zero?(-(x,26)) then zero?(0) else zero?(1)]

         import mybool
         let true = from mybool take true
         in let false = from mybool take false
         in let and = from mybool take and
         in ((and true) false)"
                   (from mybool take t) 27)
      
      (modules-booleans-test-true "
         module mybool 
          interface [abstract-type t
                     true : t
                     false : t
                     and : (t -> (t -> t))
                     not : (t -> t)
                     to-bool : (t -> bool)]
          implementation [type t = int
                          true = 26
                          false = 27
                          and = proc (x : t) 
                                 proc (y : t)
                                  if zero?(-(x,26)) then y else false
                          not = proc (x : t) 
                                 if zero?(-(x,26)) then false else true
                          to-bool = proc (x : t)  
                                     if zero?(-(x,26)) then zero?(0) else zero?(1)]

         import mybool
         let true = from mybool take true
         in let false = from mybool take false
         in let and = from mybool take and
         in ((and true) true)"
                                   (from mybool take t) 26)
      
      (modules-booleans-test-not "
         module mybool 
          interface [abstract-type t
                     true : t
                     false : t
                     and : (t -> (t -> t))
                     not : (t -> t)
                     to-bool : (t -> bool)]
          implementation [type t = int
                          true = 26
                          false = 27
                          and = proc (x : t) 
                                 proc (y : t)
                                  if zero?(-(x,26)) then y else false
                          not = proc (x : t) 
                                 if zero?(-(x,26)) then false else true
                          to-bool = proc (x : t)  
                                     if zero?(-(x,26)) then zero?(0) else zero?(1)]

         import mybool
         let true = from mybool take true
         in let false = from mybool take false
         in let and = from mybool take and
         in let not = from mybool take not
         in (not ((and true) true))"
                                  (from mybool take t) 27)
      
      (modules-booleans-test-to-bool "
         module mybool 
          interface [abstract-type t
                     true : t
                     false : t
                     and : (t -> (t -> t))
                     not : (t -> t)
                     to-bool : (t -> bool)]
          implementation [type t = int
                          true = 26
                          false = 27
                          and = proc (x : t) 
                                 proc (y : t)
                                  if zero?(-(x,26)) then y else false
                          not = proc (x : t) 
                                 if zero?(-(x,26)) then false else true
                          to-bool = proc (x : t)  
                                     if zero?(-(x,26)) then zero?(0) else zero?(1)]

         import mybool
         let true = from mybool take true
         in let false = from mybool take false
         in let and = from mybool take and
         in let not = from mybool take not
         in let tb  = from mybool take to-bool
         in (tb (not ((and true) true)))"
                                 bool #f)
      
      (int-set "
        module int-set
         interface [abstract-type t
                    empty : t
                    add-to-set :(t -> (int -> t))
                    member : (int ->(t -> bool))]
         implementation
          [type t = (int -> bool )
           type valtype = int
           empty = proc (n : int)  zero?(1)
           add-to-set
            = proc (set : t)
               proc (val : valtype)
                 proc (search-val : valtype)
                  if zero?(-(val, search-val)) 
                  then  zero?(0)
                  else (set search-val)
           member 
             = proc (search-val : valtype)
                proc (set : t)
                 (set search-val)]

          import int-set
          let empty = from int-set take empty
          in let add = from int-set take add-to-set
          in let member = from int-set take member
          in let set1 = ((add empty) 3)
          in let set2 = ((add set1) 4)
          in let set3 = ((add set2) 5)
          in if ((member 3) set3) then 5 else 6
          "
               int
               5)
(sum-times-maker-plus "
        module sum-times-maker 
         interface
          ((m1 : [abstract-type t
                  zero : t
                  succ : (t -> t)
                  pred : (t -> t)
                  is-zero : (t -> bool)]) 
            => [plus : (from m1 take t 
                        -> (from m1 take t -> from m1 take t))
               ])
         implementation 
          module-proc 
           (m1 : [abstract-type t
                  zero : t
                  succ : (t -> t)
                  pred : (t -> t)
                  is-zero : (t -> bool)])
           [plus 
             = let z? = from m1 take is-zero
               in let p = from m1 take pred
               in let s = from m1 take succ
               in letrec (from m1 take t -> from m1 take t)  plus (x : from m1 take t) 
                 = proc(y : from m1 take t) 
                     if (z? x)   
                   then y
                   else (s ((plus (p x)) y))
               in plus]

        module int1
         interface [abstract-type t
                    zero : t
                    succ : (t -> t)
                    pred : (t -> t)
                    is-zero : (t -> bool)]  
         implementation [type t = int
                         zero = 0
                         succ = proc(x : ?) -(x,-1)
                         pred = proc(x : ?) -(x,1)
                         is-zero = proc (x : ?) zero?(x)
                         ]

        module sum-prod-int1
         interface [plus : (from int1 take t 
                        -> (from int1 take t -> from int1 take t))
               ]
         implementation  
          import sum-times-maker 
          import int1
          (sum-times-maker  int1)

        import int1
        import sum-prod-int1
        let z? = from int1 take is-zero
        in let p  = from int1 take pred
        in let two1 = (from int1 take succ
                    (from int1 take succ
                     from int1 take zero))
        in letrec int to-int (x : from int1 take t) =
                       if (z? x) then 0
                          else -((to-int (p x)), -1)

        in (to-int ((from sum-prod-int1 take plus 
            two1) two1))"
            int 4)

(sum-times-maker-times "
        module sum-times-maker 
         interface
          ((m1 : [abstract-type t
                  zero : t
                  succ : (t -> t)
                  pred : (t -> t)
                  is-zero : (t -> bool)]) 
            => [plus : (from m1 take t 
                        -> (from m1 take t -> from m1 take t))
                times : (from m1 take t 
                        -> (from m1 take t -> from m1 take t))
               ])
         implementation 
          module-proc 
           (m1 : [abstract-type t
                  zero : t
                  succ : (t -> t)
                  pred : (t -> t)
                  is-zero : (t -> bool)])
           [plus 
             = let z? = from m1 take is-zero
               in let p = from m1 take pred
               in let s = from m1 take succ
               in letrec (from m1 take t -> from m1 take t)  plus (x : from m1 take t) 
                 = proc(y : from m1 take t) 
                     if (z? x)   
                   then y
                   else (s ((plus (p x)) y))
               in plus
            times
             = let zero = from m1 take  zero
               in let z? = from m1 take is-zero
               in let p = from m1 take pred
               in let s = from m1 take succ
               in letrec (from m1 take t -> from m1 take t)  times (x : from m1 take t) 
                 = proc(y : from m1 take t) 
                    letrec (from m1 take t -> (  from m1 take t -> from m1 take t))
                              times-help (a : from m1 take t)
                               = proc(b : from m1 take t) 
                                   proc(c : from m1 take t)
                                     if (z? c) then a
                                       else 
                                         (((times-help  ((plus a) b)) b) (p c))
                       in (((times-help zero) x ) y)  
                 in times]

        module int1
         interface [abstract-type t
                    zero : t
                    succ : (t -> t)
                    pred : (t -> t)
                    is-zero : (t -> bool)]  
         implementation [type t = int
                         zero = 0
                         succ = proc(x : ?) -(x,-1)
                         pred = proc(x : ?) -(x,1)
                         is-zero = proc (x : ?) zero?(x)
                         ]

        module sum-prod-int1
         interface [plus : (from int1 take t 
                        -> (from int1 take t -> from int1 take t))
                   times : (from int1 take t 
                        -> (from int1 take t -> from int1 take t))
               ]
         implementation  
          import sum-times-maker 
          import int1
          (sum-times-maker  int1)

        import int1
        import sum-prod-int1
        let z = from int1 take zero
        in let z? = from int1 take is-zero
        in let p  = from int1 take pred
        in let two1 = (from int1 take succ
                    (from int1 take succ
                     from int1 take zero))
        in letrec int to-int (x : from int1 take t) =
                       if (z? x) then 0
                          else -((to-int (p x)), -1)

        in (to-int 
                ((from sum-prod-int1 take times
                      two1) two1)
                   )"
            int 4)


 
      ))

  (define tests-for-run
    (let loop ((lst the-test-suite))
      (cond
        ((null? lst) '())
        ((= (length (car lst)) 4)
          (printf "creating item: ~s~%" (caar lst))
         (cons
           (list
             (list-ref (car lst) 0)
             (list-ref (car lst) 1)
             (list-ref (car lst) 3))
           (loop (cdr lst))))
        (else (loop (cdr lst))))))

  ;; ok to have extra members in a test-item.
  (define tests-for-check the-test-suite)

  (define tests-for-parse the-test-suite)

  )

